package com.miplus.ccrm.core.service.collect;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.miplus.ccrm.common.*;
import com.miplus.ccrm.core.controller.vo.ficase.*;
import com.miplus.ccrm.core.mapper.*;
import com.miplus.ccrm.core.pojo.*;
import com.miplus.ccrm.core.service.ExportService;
import com.miplus.ccrm.core.service.cust.ConContactService;
import com.miplus.ccrm.core.service.cust.ConCustomerService;
import com.miplus.ccrm.core.service.strategy.CpCalllistService;
import com.miplus.ccrm.core.service.strategy.CpStrategyService;
import com.miplus.ccrm.core.utils.EnumFiChannel;
import com.miplus.ccrm.core.utils.EnumTaskStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author pc
 * @description 针对表【fi_task】的数据库操作Service实现
 * @createDate 2024-04-08 23:55:42
 */
@Slf4j
@Service
public class FiTaskServiceImpl extends MPJBaseServiceImpl<FiTaskMapper, FiTask>
        implements FiTaskService {

    @Resource
    private FiTaskHistService fiTaskHistService;
    @Resource
    private CpStrategyService cpStrategyService;
    //这里不能在定义fiCreditcasesService了
    @Resource
    private FiCreditcasesMapper fiCreditcasesMapper;
    @Resource
    private CpCalllistService cpCalllistService;
    @Resource
    private CreditAccountMapper creditAccountMapper;
    @Resource
    private ConCustomerService conCustomerService;
    @Resource
    private FiImportHistService fiImportHistService;
    @Resource
    private FiTaskOldhistMapper fiTaskOldhistMapper;
    @Resource
    private ExportService exportService;
    @Resource
    private ConContactService conContactService;
    @Resource
    private QmDataMapper qmDataMapper;
    @Resource
    private ObCallCaseMapper obCallCaseMapper;

    private static String  FITASK_CASETYPE="COLLECT";

    @Override
    public Integer addTask(String $usrid, String clid, Integer originnumber,
                           Integer channel, Integer contactnumber, String phone,String cticallid)
    {
        FiCreditcases ficases=fiCreditcasesMapper.selectById(originnumber);
        return addTask($usrid,clid,originnumber,ficases.getCreditAcct(),channel,
                contactnumber,phone,cticallid,null,null,null,null,null);
    }

    @Override
    public Integer addTask(String usrid, String clid, Integer originnumber, String acctno, Integer channel, Integer contactnumber,
                           String phone, String cticallid, String result, String resultdsc, String batchid, Date dodt, String status)
    {//addTask 里面增加result，resultdsc是为了导入催记历史时一次即可，不需要update提交了
        FiTask task=new FiTask();
        task.setClid(clid);
        task.setOriginnumber(originnumber);
        task.setOriginkey(acctno);
        task.setChannel(channel);
        if(contactnumber!=null) {
            task.setContactnumber(contactnumber);
        }
        task.setPhone(phone);
        task.setOrigintype(FITASK_CASETYPE);
        if(JPubUtils.IsEmpty(status)){
            if (JPubUtils.IsEmpty(result)) {
                task.setStatus("O"); //处理中，对应字典：FITASK.STATUS
            } else {
                status = cpStrategyService.getTaskStatus(clid, result);
                task.setStatus(status);
            }
        }
        task.setStatus(status);
        if(JPubUtils.IsNotEmpty(result)) {
            task.setResult(result);
        }
        if (JPubUtils.IsEqual(status, "R") ||
                JPubUtils.IsEqual(status, "F")) {
            task.setSendtimes(1);
            task.setTaskenddt(new Date());
        }else{
            task.setSendtimes(0);
        }
        if(JPubUtils.IsEmpty(task.getStatus())){
            task.setStatus("O");
        }

        if(JPubUtils.IsNotEmpty(cticallid)){
            task.setCticallid(cticallid);
        }
        if(JPubUtils.IsNotEmpty(resultdsc)){
            task.setResultdsc(resultdsc);
        }
        if(JPubUtils.IsNotEmpty(batchid)){
            task.setBatchid(batchid);
        }
        task.setPriority(1000);
        task.setDousr(usrid);
        if(dodt!=null) {
            task.setDodt(dodt);
        }else{
            task.setDodt(new Date());
        }
        task.setCrusr(usrid);
        task.setCrdt(new Date());
        task.setMdusr(usrid);
        task.setMddt(new Date());

        baseMapper.insert(task);

        //写历史记录
        FiTaskHist fiTaskHist=new FiTaskHist();
        BeanUtils.copyProperties(task,fiTaskHist);

        fiTaskHistService.getBaseMapper().insert(fiTaskHist);

        return task.getTasknumber();
    }

    @Override
    public Integer addTask(String $usrid, String clid, Integer originnumber, Integer channel)
    {
        return addTask($usrid,clid, originnumber,channel,null,"",null);
    }

    @Override
    public Integer addTask(String usrid, String clid, String acctno,Integer channel,String phone,
                           String result,String resultdsc,String batchid,Date dodt,String status)
    {
        FiCreditcases ficases=fiCreditcasesMapper.selectOne(
                new QueryWrapper<FiCreditcases>().eq("credit_acct",acctno));
        if(ficases==null){
            log.warn("addTask:acctno={} nofindficase",acctno);
            return 0;
        }

        return addTask(usrid,clid,ficases.getCreditcaseid(),acctno,channel,
                null,phone,null,result,resultdsc,batchid,dodt,status);
    }

    @Override
    public Integer addTask(String usrid, String clid, String acctno,Integer channel,String phone,String batchid, String cticallid)
    {
        FiCreditcases ficases=fiCreditcasesMapper.selectOne(
                new QueryWrapper<FiCreditcases>().eq("credit_acct",acctno));
        if(ficases==null){
            log.warn("addTask:acctno={} nofindficase",acctno);
            return 0;
        }

        return addTask(usrid,clid,ficases.getCreditcaseid(),acctno,channel,
                null,phone,cticallid,null,null,batchid,new Date(),null);
    }

    @Override
    public Integer addTask(String usrid, String clid, Integer originnumber,Integer channel,Integer contactnumber,String phone, String result,String resultdsc)
    {
        FiCreditcases ficases=fiCreditcasesMapper.selectOne(
                new QueryWrapper<FiCreditcases>().eq("creditcaseid",originnumber));
        if(ficases==null){
            log.warn("addTask:ficaseid={} noacct",originnumber);
            return 0;
        }

        return addTask(usrid,clid,originnumber,ficases.getCreditAcct(),channel,
                contactnumber,phone,null,result,resultdsc,null,null,null);
    }

    @Override
    public Integer addTask(String $usrid,String clid,Integer originnumber, Integer channel,String result, String resultdsc)
    {
        return addTask($usrid,clid,originnumber,channel,null,null,result,resultdsc);
    }

    @Override
    public int updateStatus(Integer tasknumber, String $usrid,String status)
    {
        FiTask task=new FiTask();
        task.setTasknumber(tasknumber);
        task.setStatus(status);
        task.setMdusr($usrid);
        task.setMddt(new Date());
        int ret=baseMapper.updateById(task);

        task=baseMapper.selectById(tasknumber);

        //写历史记录
        FiTaskHist fiTaskHist=new FiTaskHist();
        BeanUtils.copyProperties(task,fiTaskHist);
        fiTaskHistService.getBaseMapper().insert(fiTaskHist);

        return ret;
    }

    @Override
    public String getTaskStatus(Integer tasknumber,String result)
    {
        String ret="O";
        FiTask fiTask=selectJoinOne(FiTask.class,
                new MPJLambdaWrapper<FiTask>()
                        .selectAll(FiTask.class)
                        .eq(FiTask::getTasknumber,tasknumber)
        );
        if(JPubUtils.IsEmpty(fiTask.getClid())){
            ret="F";
        }
        else{
            ret=cpStrategyService.getTaskStatus(fiTask.getClid(),result);
        }
        return ret;
    }

    @Override
    public int saveTask(Integer tasknumber, String $usrid, String result, String resultdsc,
                        String ptpstatus, BigDecimal ptp, Date ptpdt, Date appointdt) {
        return saveTask(tasknumber,$usrid,1,result,resultdsc,ptpstatus,ptp,ptpdt,appointdt,null);
    }

    @Override
    public int saveTask(Integer tasknumber,String $usrid, String result, String resultdsc,
                        String ptpstatus, BigDecimal ptp, Date ptpdt)
    {
        return saveTask(tasknumber,$usrid,1,result,resultdsc,ptpstatus,ptp,ptpdt,null,null);
    }

    @Override
    public int saveTask(Integer tasknumber, String $usrid, String result, String resultdsc,String status){
        return saveTask(tasknumber,$usrid,1,result,resultdsc,null,null,null,null,status);
    }

    @Override
    public int saveTask(Integer tasknumber, String $usrid,Integer sendtimes, String result, String resultdsc,
                        String ptpstatus, BigDecimal ptp, Date ptpdt, Date appointdt,String tkstatus)
    {
        String status=tkstatus;
        if(JPubUtils.IsEmpty(status)) {
            status=getTaskStatus(tasknumber, result);
        }
        FiTask task=new FiTask();
        task.setTasknumber(tasknumber);
        task.setResult(result);
        if(JPubUtils.IsNotEmpty(resultdsc)) {
            task.setResultdsc(resultdsc);
        }
        if(JPubUtils.IsNotEmpty(sendtimes)) {
            task.setSendtimes(sendtimes);
        }
        else task.setSendtimes(1);
        if(ptp!=null) {
            task.setPtp(ptp);
        }
        if(ptpdt!=null) {
            task.setPtpdt(ptpdt);
        }
        if(ptpstatus!=null) {
            task.setPtpstatus(ptpstatus);
        }
        task.setStatus(status);
        task.setDousr($usrid);
        task.setDodt(new Date());
        task.setMdusr($usrid);
        task.setMddt(new Date());
        if(appointdt!=null) {
            task.setAppointdt(appointdt);
        }
        if(JPubUtils.IsEqual(status,"R")||
                JPubUtils.IsEqual(status,"F")) {
            task.setTaskenddt(new Date());
        }

        int ret=baseMapper.updateById(task);

        //写历史记录
        FiTask task2=baseMapper.selectById(tasknumber);
        FiTaskHist fiTaskHist=new FiTaskHist();
        BeanUtils.copyProperties(task2,fiTaskHist);

        fiTaskHistService.getBaseMapper().insert(fiTaskHist);

        return ret;
    }

    @Override
    public CmdResVo addDialTask(String $usrid, TaskCallAddVo paras)
    {
        String clid=paras.getClid();
        if(JPubUtils.IsEmpty(clid)){
            clid="SYS_CALL";
        }
        Integer channel=paras.getChannel();
        if(JPubUtils.IsEmpty(channel)){
            channel= EnumFiChannel.Phone.value;
        }

        String phn=paras.getPhone();
        if(phn.indexOf("*")>0){//2024-07-08
            phn=conContactService.getPhone(paras.getContactnumber());
            log.info("addDialTask：Phone={}->{}",paras.getPhone(),phn);
        }

        //2024-10-10 去掉客户端重复提交
        FiTask fiTask=selectJoinOne(FiTask.class,
                new MPJLambdaWrapper<FiTask>()
                        .selectAll(FiTask.class)
                        .eq(FiTask::getClid,"SYS_CALL")
                        .eq(FiTask::getOriginnumber,paras.getFicaseid())
                        .eq(FiTask::getCticallid,paras.getCticallid())
                        .eq(FiTask::getPhone,phn)
                        .eq("rownum",1)
        );
        Integer tasknumber=0;
        if(fiTask==null) {
            tasknumber = addTask($usrid, clid, paras.getFicaseid(), channel,
                    paras.getContactnumber(), phn, paras.getCticallid()
            );
        }
        else {
            tasknumber = fiTask.getTasknumber();
            log.warn("addDialTask：Duplicate submissions Ficaseid={},Cticallid={}",paras.getFicaseid(),paras.getCticallid());
        }

        return new CmdResVo(1,tasknumber.toString());
    }

    @Override
    public CmdResVo saveDialTask(String $usrid, TaskCallSaveVo paras)
    {
        int ret=saveTask(paras.getTasknumber(),$usrid,paras.getResult(),paras.getResultdsc(),
                paras.getPtpstatus(),paras.getPtp(),paras.getPtpdt(),paras.getAppointdt());

        return new CmdResVo(ret,paras.getTasknumber().toString());
    }

    @Override
    public CmdResVo addSmsTask(String $usrid, TaskSmsAddVo paras)
    {
        String clid=paras.getClid();
        if(JPubUtils.IsEmpty(clid)){
            clid="SYS_SMS";
        }
        Integer channel=paras.getChannel();
        if(JPubUtils.IsEmpty(channel)){
            channel=EnumFiChannel.Sms.value;
        }
        String phn=paras.getPhone();
        if(phn.indexOf("*")>0){//2024-07-08
            phn=conContactService.getPhone(paras.getContactnumber());
            log.info("addSmsTask：Phone={}->{}",paras.getPhone(),phn);
        }

        Integer tasknumber=addTask($usrid,clid,paras.getFicaseid(),channel,
                paras.getContactnumber(),phn,null
        );

        return new CmdResVo(1,tasknumber.toString());
    }

    @Override
    public CmdResVo saveSmsTask(String $usrid, TaskSmsSaveVo paras)
    {
        int ret=saveTask(paras.getTasknumber(),$usrid,paras.getResult(),paras.getResultdsc(),
                null,null,null);

        return new CmdResVo(ret,paras.getTasknumber().toString());
    }

    @Override
    public List<FiTaskCurrVo> getCurrentTask(Integer ficaseid)
    {//案件号一样，可以多次外访，但是状态是N,O,P的只有一个
        return selectJoinList(FiTaskCurrVo.class,
                new MPJLambdaWrapper<FiTask>()
                        .selectAs(FiTask::getStatus,FiTaskCurrVo::getState)
                        .selectAs("fun_getnames('CAMPAIGN.CHANNEL',cp.channel)",FiTaskCurrVo::getChannelname)
                        .leftJoin(CpCalllist.class,"cp",CpCalllist::getClid,FiTask::getClid)
                        .select(FiTask::getTasknumber,FiTask::getClid,FiTask::getStatus)
                        .select(CpCalllist::getName,CpCalllist::getChannel,CpCalllist::getWfid)
                        .in(FiTask::getStatus,"O","N","P")
                        .eq(CpCalllist::getApptype,"1")
                        .eq(FiTask::getOriginnumber,ficaseid)
        );
    }

    @Override
    public IPage<FiTaskResVo> taskHist(JSysUser user, FiTaskReqVo paras)
    {
        //fi_gettaskresult(t.clid,t.result)='联系成功'，在TDSQL里面执行有字符集问题，2024-09-26
        String $usrid=user.getUsrid();
        String phnstar= JUsrPerm.getPermission(user,JUsrPerm.DISSTAR_PHN);
        String idstar= JUsrPerm.getPermission(user,JUsrPerm.DISSTAR_IDNO);
        return selectJoinListPage(new Page<>(paras.getPageNum(), paras.getPageSize()),
                FiTaskResVo.class,
                new MPJLambdaWrapper<FiTask>()
                        .selectAs("fun_getnames('CAMPAIGN.CHANNEL',t.channel)",FiTaskResVo::getChannel)
                        .selectAs("fun_getnames('FITASK.STATUS',t.status)",FiTaskResVo::getStatus)
                        .selectAs("fun_getnames('CON.RELATION',ct.relational)",FiTaskResVo::getRelational)
                        .selectAs("fun_getnames('FI.REPAY.WILL',t.ptpstatus)",FiTaskResVo::getPtpstatusdsc)
                        .selectAs(FiTask::getOriginnumber,FiTaskResVo::getFicaseid)
                        .selectAs("fun_getnames('COLLECT.STATUS',fi.status)",FiTaskResVo::getFicasestatus)
                        .selectAs("ct.name",FiTaskResVo::getContactname)
                        .selectAs("fi_gettaskresult(t.clid,t.result)",FiTaskResVo::getResult)
                        .selectAs(String.format("fi_starSecu('%s','%s',t.phone,'%s')",$usrid,JUsrPerm.DISSTAR_PHN,phnstar),FiTaskResVo::getPhone)
                        .selectAs(String.format("fi_starSecu('%s','%s',cu.openacctcertno,'%s')", $usrid, JUsrPerm.DISSTAR_IDNO, idstar), FiTaskResVo::getOpenacctcertno)
                        .leftJoin(FiCreditcases.class,"fi",FiCreditcases::getCreditcaseid,FiTask::getOriginnumber)
                        .leftJoin(ConCustomer.class,"cu",ConCustomer::getCustomernumber,FiCreditcases::getCustomernumber)
                        .leftJoin(ConContact.class,"ct",ConContact::getContactnumber,FiTask::getContactnumber)
                        .select(FiTask::getTasknumber,FiTask::getCrusr,FiTask::getResultdsc,
                                FiTask::getDousr,FiTask::getPriority,FiTask::getCrdt,FiTask::getAppointdt,FiTask::getDodt,
                                FiTask::getPtp,FiTask::getPtpdt,FiTask::getCticallid
                        )
                        .select(ConCustomer::getCustname,ConCustomer::getCustomernumber)
                        .eq(JPubUtils.IsNotEmpty(paras.getFicaseid()),FiTask::getOriginnumber,paras.getFicaseid())
                        .apply(JPubUtils.IsEmpty(paras.getFicaseid()),"fc_hasUsrInMgr(t.crusr,{0})>0",$usrid)
                        .eq(JPubUtils.IsNotEmpty(paras.getChannel()),FiTask::getChannel,paras.getChannel())
                        .eq(JPubUtils.IsNotEmpty(paras.getPhone()),FiTask::getPhone,paras.getPhone())
                        .eq(JPubUtils.IsNotEmpty(paras.getCustname()),ConCustomer::getCustname,paras.getCustname())
                        .eq(JPubUtils.IsNotEmpty(paras.getCustno()),ConCustomer::getCustomernumber,paras.getCustno())
                        .eq(JPubUtils.IsNotEmpty(paras.getPtpstatus()),FiTask::getPtpstatus,paras.getPtpstatus())
                        .eq(JPubUtils.IsNotEmpty(paras.getCrusr()),FiTask::getCrusr,paras.getCrusr())
                        .eq(JPubUtils.IsNotEmpty(paras.getBatchid()),FiTask::getBatchid,paras.getBatchid())
                        .eq(JPubUtils.IsNotEmpty(paras.getOpenacctcertno()),ConCustomer::getOpenacctcertno,paras.getOpenacctcertno())
                        .exists(JPubUtils.IsNotEmpty(paras.getResult()),String.format("SELECT 1 FROM cp_strategy cp WHERE cp.clid = t.clid and cp.ccc=t.result AND (cp.ccc='%s' or cp.helpstr='%s')",paras.getResult(),paras.getResult()))
                        .between(JPubUtils.IsNotEmpty(paras.getStartdt()), FiTask::getCrdt,JPubUtils.StringToDate(paras.getStartdt()),JPubUtils.StringToDate(paras.getEnddt()))
                        .like(JPubUtils.IsNotEmpty(paras.getResultdsc()),FiTask::getResultdsc,paras.getResultdsc())
                        .in(JPubUtils.IsNotEmpty(paras.getOpenacctcertnolist()), ConCustomer::getOpenacctcertno, paras.getOpenacctcertnolist())
                        .in(JPubUtils.IsNotEmpty(paras.getCustnolist()),ConCustomer::getCustomernumber,paras.getCustnolist())
                        .orderByAsc(FiTask::getPriority)
                        .orderByDesc(FiTask::getDodt)
        );
    }

    @Override
    public CmdResVo taskTopSet(Integer tasknumber,Integer toppos)
    {
        FiTask fi=baseMapper.selectById(tasknumber);
        List<FiTask> taskList=selectJoinList(FiTask.class,
                new MPJLambdaWrapper<FiTask>()
                        .select(FiTask::getOriginnumber,FiTask::getPriority)
                        .le(FiTask::getPriority,10)
                        .isNotNull(FiTask::getOriginnumber)
                        .eq(FiTask::getOriginnumber,fi.getOriginnumber())
        );
        if(taskList.size()>=3){
            throw new ServiceException(EnumRCode.TopMix.value, EnumRCode.TopMix.name);
        }
        fi=new FiTask();
        fi.setTasknumber(tasknumber);
        if(JPubUtils.IsEmpty(toppos)){
            fi.setPriority(1);
            for(FiTask upfi:taskList){
                upfi.setPriority(upfi.getPriority()+1);
                baseMapper.updateById(upfi);
            }
        }else{
            fi.setPriority(toppos);
        }

        int ret=baseMapper.updateById(fi);

        return new CmdResVo(ret,tasknumber.toString());
    }

    @Override
    public CmdResVo taskTopCancel(Integer tasknumber)
    {
        FiTask fi=new FiTask();
        fi.setTasknumber(tasknumber);
        fi.setPriority(1000);

        int ret=baseMapper.updateById(fi);

        return new CmdResVo(ret,tasknumber.toString());
    }

    @Override
    @Transactional
    public ImpResultVo impTaskList(String $usrid,FiTaskImpVo paras)
    {//批量导入离线催记
        SimpleDateFormat sdf=new SimpleDateFormat("yyMMddHHmmssSSS");
        String batchid ="L"+sdf.format(new Date());

        String tempid=paras.getTempid();
        if(JPubUtils.IsEmpty(tempid)){
            tempid="offtask";
        }

        int ret=0;
        ImpResultVo impResultVo=new ImpResultVo();
        List<String> fails=new LinkedList<>();
        log.info("impTaskList:batchid={},Count={}",batchid,paras.getAddVoList().size());

        for(FiTaskAddVo fiAdd:paras.getAddVoList()){
            String acctno=fiAdd.getAcctno().trim();
            if(JPubUtils.IsTrimEmpty(fiAdd.getChannel())){
                log.warn("impTaskList:channel null:{}",fiAdd.getChannel());
                fails.add(acctno+":没有催记动作");
                continue;
            }
            String channel=fiAdd.getChannel().trim();
            EnumFiChannel fiChannel=EnumFiChannel.AsFiChannel(channel);
            if(fiChannel==EnumFiChannel.Unknow){//最好前台页面做一下校验提醒
                log.warn("impTaskList:nochannel {}",channel);
                fails.add(acctno+":没对应催记动作:"+channel);
                continue;
            }
            Date dodt=JPubUtils.StringToDate(fiAdd.getDodt());
            if(dodt==null) {
                dodt = new Date();
            }
            String tkstatus=null;
            String ccc=null;
            String clid = "SYS_CALL";
            if(JPubUtils.IsNotEmpty(fiAdd.getResult())&&JPubUtils.IsNotEmpty(clid)) {
                ccc = cpStrategyService.getCcc(clid, fiAdd.getResult().trim());
            }
            else tkstatus= EnumTaskStatus.R.toString();

            String usrid=fiAdd.getDousrid();
            if(JPubUtils.IsTrimEmpty(usrid)){
                usrid=$usrid;
            }
            log.info("impTaskList:batchid={},clid={},acctno={},ccc={},tkstatus={},channel={}({})",
                    batchid,clid,acctno,ccc,tkstatus,channel,fiChannel.value
            );
            addTask(usrid,clid,acctno,fiChannel.value,
                    JPubUtils.Trim(fiAdd.getPhone()),ccc,JPubUtils.Trim(fiAdd.getRemark()),batchid,dodt,tkstatus
            );
            ret++;
        }

        if(ret>0) {
            fiImportHistService.AddImportHist(batchid, paras.getBatchdsc(), $usrid,
                    tempid, paras.getFilename(),
                    paras.getAddVoList().size(), ret);
        }
        impResultVo.setBatchid(batchid);
        impResultVo.setOkcnt(ret);
        impResultVo.setFailcnt(fails.size());
        impResultVo.setFaillist(fails);
        return impResultVo;
    }

    @Override
    @Transactional
    public ImpResultVo impTaskCmdList(String $usrid, TaskCmdImpVo paras)
    {//批量增加（导入）导入催收函/诉讼/支付令，记录催记
        SimpleDateFormat sdf=new SimpleDateFormat("yyMMddHHmmssSSS");
        String batchid = "C"+sdf.format(new Date());

        int ret=0;
        ImpResultVo impResultVo=new ImpResultVo();
        List<String> fails=new LinkedList<>();
        EnumFiChannel fiChannel=EnumFiChannel.AsFiChannelBy(paras.getTempid());
        log.info("impTaskCmdList:tempid={},batchid={},Count={},Channel={}",
                paras.getTempid(),batchid,paras.getAddVoList().size(),fiChannel
        );
        if(fiChannel==EnumFiChannel.Unknow){
            throw new ServiceException(EnumRCode.NoChannel.value, EnumRCode.NoChannel.name);
        }
        String clid = cpCalllistService.getClid(fiChannel.value);
        for(TaskCmdAddVo fiAdd : paras.getAddVoList()){
            String acctno=fiAdd.getAcctno().trim();
            CreditAccount account=creditAccountMapper.selectOne(
                    new QueryWrapper<CreditAccount>().eq("acct",acctno)
            );
            if(account==null){
                log.warn("impTaskCmdList:nofind acctno={}",acctno);
                fails.add(acctno);
                continue;
            }
            Date dodt=JPubUtils.StringToDate(fiAdd.getDodt());
            if(dodt==null) {
                dodt = new Date();
            }
            String tkstatus=null;
            String ccc=null;
            if(JPubUtils.IsNotEmpty(fiAdd.getResult())){
                if(JPubUtils.IsNotEmpty(clid)) {
                    ccc = cpStrategyService.getCcc(clid, fiAdd.getResult().trim());
                }
                else{
                    ccc=fiAdd.getResult().trim();
                }
            }
            if(JPubUtils.IsEmpty(clid)){
                tkstatus=EnumTaskStatus.R.toString();
            }
            String custno=account.getCustNo();
            log.info("impTaskCmdList:batchid={},acctno={},ccc={},tkstatus={},channel={},addtag={}",
                    batchid,acctno,ccc,tkstatus,fiChannel.value,fiChannel.toString().toUpperCase()
            );
            addTask($usrid,clid,acctno,fiChannel.value,
                    null,ccc,JPubUtils.Trim(fiAdd.getRemark()),batchid,dodt,tkstatus
            );

            if(fiChannel!=EnumFiChannel.Letter) { //催收不打标签2024-05-20
                conCustomerService.addTag(custno, "SYS", fiChannel.toString().toUpperCase(), batchid);
            }

            ret++;
        }
        if(ret>0) {
            fiImportHistService.AddImportHist(batchid,paras.getBatchdsc(), $usrid,
                    paras.getTempid(), paras.getFilename(),
                    paras.getAddVoList().size(), ret);
        }
        impResultVo.setBatchid(batchid);
        impResultVo.setOkcnt(ret);
        impResultVo.setFailcnt(fails.size());
        impResultVo.setFaillist(fails);

        return impResultVo;
    }

    @Override
    @Transactional
    public CmdResVo delImpTaskList(TaskBatchDelVo paras)
    {
        String tempid=paras.getTempid();
        int ret=0;
        if(JPubUtils.IsEqual(tempid,"histtask")){ //历史催记
            fiTaskOldhistMapper.delete(new QueryWrapper<FiTaskOldhist>()
                    .eq("batchid",paras.getBatchid())
            );
        }
        else if(JPubUtils.IsEqual(tempid,"qmtemplate")){//质检历史
            qmDataMapper.delete(new MPJLambdaWrapper<QmData>()
                    .eq(QmData::getBatchid,paras.getBatchid())
            );
        }
        else if(JPubUtils.IsEqual(tempid,"dialtemplate")){//AICALL历史
            FiImportHist hist=fiImportHistService.getById(paras.getBatchid());
            if(hist.getStatus()==1){
                throw new ServiceException(EnumRCode.DataHasReady.value, EnumRCode.DataHasReady.name);
            }
//            obCallCaseMapper.delete(new MPJLambdaWrapper<ObCallCase>()
//                    .eq(ObCallCase::getBatchid,paras.getBatchid())
//            );
            //SQL Server 要求 DELETE 语句中的表别名必须在 FROM 子句中声明
            obCallCaseMapper.delete(new QueryWrapper<ObCallCase>()
                    .eq("batchid", paras.getBatchid())
            );
        }
        else {//离线催记及催收,司法函，支付令之类的
            ret = baseMapper.delete(new QueryWrapper<FiTask>()
                    .eq("batchid", paras.getBatchid())
            );
            fiTaskHistService.getBaseMapper().delete(new QueryWrapper<FiTaskHist>()
                    .eq("batchid", paras.getBatchid())
            );
            if (JPubUtils.IsEqual(tempid, "letter") ||
                    JPubUtils.IsEqual(tempid, "law") ||
                    JPubUtils.IsEqual(tempid, "paycmd")) {
                conCustomerService.delTag(paras.getBatchid());
            }
        }

        fiImportHistService.getBaseMapper().delete(
                new QueryWrapper<FiImportHist>().eq("batchid",paras.getBatchid())
        );

        return new CmdResVo(ret,paras.getBatchid());
    }

    @Override
    @Transactional
    public ImpResultVo impHistTaskList(String $usrid,HistTaskImpVo paras)
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyMMddHHmmssSSS");
        String batchid ="H"+sdf.format(new Date());

        String tempid=paras.getTempid();
        if(JPubUtils.IsEmpty(tempid)){
            tempid="histtask";
        }

        int ret=0;
        ImpResultVo impResultVo=new ImpResultVo();
        List<String> fails=new LinkedList<>();
        log.info("impHistTaskList:batchid={},Count={}",batchid,paras.getAddVoList().size());

        for(HistTaskAddVo fiAdd:paras.getAddVoList()){
            FiTaskOldhist def=new FiTaskOldhist();
            BeanUtils.copyProperties(fiAdd,def);
            def.setBatchid(batchid);
            if(JPubUtils.IsTrimEmpty(def.getDousr())){
                def.setDousr($usrid);
            }
            def.setDodt(JPubUtils.StringToDate(fiAdd.getDodt()));
            def.setUpdt(new Date());
            def.setUpusr($usrid);

            fiTaskOldhistMapper.insert(def);

            ret++;
        }
        if(ret>0){
            fiImportHistService.AddImportHist(batchid, paras.getBatchdsc(), $usrid,
                    tempid, paras.getFilename(),
                    paras.getAddVoList().size(), ret);
        }

        impResultVo.setBatchid(batchid);
        impResultVo.setOkcnt(ret);
        impResultVo.setFailcnt(fails.size());
        impResultVo.setFaillist(fails);

        return impResultVo;
    }

    @Override
    public CmdResVo saveAsExcel(JSysUser user, FiTaskReqVo paras, HttpServletResponse response)
    {
        String $usrid=user.getUsrid();
        IPage<FiTaskResVo> pages=taskHist(user, paras);
        ArrayList arr=new ArrayList();

        String exptempid=JPubUtils.getExpTempID(paras.getExpfilename(),"催记列表");
        String filename=JPubUtils.getExpFileName(
                paras.getExpfilename(),exptempid
        );
        pages.convert(u->{
            HashMap map=JPubUtils.toExportMap(u);
            if(map!=null) arr.add(map);
            return u;
        });
        CmdResVo resVo=exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                $usrid
        );

        int okcount=resVo.getCount();
        if(okcount>0){
            fiImportHistService.AddExportHist(
                    resVo.getKeyId(),
                    $usrid,
                    exptempid,
                    filename,
                    okcount
            );
        }

        return resVo;
    }
}
